using System;
using System.Xml.Serialization;
using Microsoft.Office.Server.Search.Administration;

namespace Carlsberg.SSPC.SearchScopes.BO
{
    public class Rule
    {
        private int ruleType;
        private int filterBehavior;
        private string propertyName;
        private string propertyValue;
        private string matchingString;
        private int urlRuleType;

        [XmlAttribute]
        public int RuleType
        {
            get { return ruleType; }
            set { ruleType = value; }
        }

        [XmlAttribute]
        public int FilterBehavior
        {
            get { return filterBehavior; }
            set { filterBehavior = value; }
        }

        [XmlAttribute]
        public string PropertyName
        {
            get { return propertyName; }
            set { propertyName = value; }
        }

        [XmlAttribute]
        public string PropertyValue
        {
            get { return propertyValue; }
            set { propertyValue = value; }
        }

        [XmlAttribute]
        public string MatchingString
        {
            get { return matchingString; }
            set { matchingString = value; }
        }

        [XmlAttribute]
        public int UrlRuleType
        {
            get { return urlRuleType; }
            set { urlRuleType = value; }
        }

        public Rule()
        {
        }

        public Rule( ScopeRule scopeRule)
        {
            filterBehavior = (int)scopeRule.FilterBehavior;

            //scopeRule.ID;
            ruleType = (int)scopeRule.RuleType;

            if( scopeRule is AllContentScopeRule)
            {
                //No properties
            }
            else if( scopeRule is PropertyQueryScopeRule)
            {
                propertyName = ((PropertyQueryScopeRule) scopeRule).Property.Name;
                propertyValue = ((PropertyQueryScopeRule) scopeRule).Value;
            }
            else if( scopeRule is UrlScopeRule)
            {
                matchingString = ((UrlScopeRule) scopeRule).MatchingString;
                urlRuleType = (int)((UrlScopeRule) scopeRule).UrlRuleType;
            }
            else
            {
                throw new ArgumentException("Unkown scoperule type:" + scopeRule.RuleType, "scopeRule");
            }
        }


        /// <summary>
        /// Create (and add) scope rule to the given rule collection.
        /// </summary>
        /// <param name="scopeRuleCollection"></param>
        /// <param name="searchContext"></param>
        /// <returns>The rule that has been added</returns>
        public ScopeRule AddScopeRule(ScopeRuleCollection scopeRuleCollection, SearchContext searchContext)
        {
            ScopeRule rule;            

            switch( (ScopeRuleType)ruleType )
            {
                case ScopeRuleType.AllContent:
                    rule = scopeRuleCollection.CreateAllContentRule();
                    break;

                case ScopeRuleType.PropertyQuery:
                    //find the managed property in question
                    Schema schema = new Schema(searchContext);
                    if( !schema.AllManagedProperties.Contains(propertyName) )
                    {
                        throw new ArgumentException("Unable to find managed property:" + propertyName);
                    }

                    rule =
                        scopeRuleCollection.CreatePropertyQueryRule((ScopeRuleFilterBehavior) filterBehavior, 
                            schema.AllManagedProperties[propertyName],
                            propertyValue);
                    break;

                case ScopeRuleType.Url:
                    rule = scopeRuleCollection.CreateUrlRule((ScopeRuleFilterBehavior) filterBehavior, 
                        (UrlScopeRuleType) urlRuleType, 
                        matchingString);
                    break;

                default:
                    throw new ArgumentException("Unknown rule type:" + ruleType);
            }

            return rule;            
        }
    }
}
